/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

package com.huawei.saas.properties;

import com.huawei.saas.constants.Constants;
import com.huawei.saas.utils.MapUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 动态数据源配置属性
 *
 * @author lWX1156935
 * @since 2022/4/22
 */
@ConfigurationProperties(prefix = DynamicSourceProperties.PREFIX)
@Data
@RefreshScope
@Log4j2
@EqualsAndHashCode(callSuper = false)
public class DynamicSourceProperties extends PoolProperties {
    /**
     * 配置前缀
     */
    public static final String PREFIX = "spring.datasource.dynamic";

    /**
     * 是否开启配置
     */
    private boolean enable;

    /**
     * 默认源
     */
    private String defaultSource;

    /**
     * 数据源及其配置 key = groupName
     */
    private Map<String, MasterSlaveProperty> dataSourceMap;

    /**
     * 租户与数据源绑定关系
     */
    private Map<String, DataSourceBindingProperty> bindingMap;

    /**
     * 设置数据源组时，组名填充
     *
     * @param dataSourceMap 数据源组
     */
    public void setDataSourceMap(Map<String, MasterSlaveProperty> dataSourceMap) {
        if (MapUtils.isEmpty(dataSourceMap)) {
            return;
        }
        dataSourceMap.entrySet().stream().forEach(entry -> {
            String key = entry.getKey();
            MasterSlaveProperty masterSlaveProperty = entry.getValue();
            Optional.ofNullable(masterSlaveProperty).ifPresent(dataSource -> {
                dataSource.setGroupName(key);
                setGroupBindPath(masterSlaveProperty, key);
                setMasterBindPath(masterSlaveProperty.getMaster(), key);
                setSlaveBindPath(masterSlaveProperty.getSlave(), key);
            });
        });
        this.dataSourceMap = dataSourceMap;

        // 设置本层连接池绑定路径
        this.setPoolBeanBindingPath(String.join(Constants.DOT, PREFIX, Constants.MULTI_POOL_PROPERTY_APPEND));
    }

    /**
     * 数据源组的绑定路径
     *
     * @param dataSource 数据源组
     * @param groupName 组名
     */
    private void setGroupBindPath(MasterSlaveProperty dataSource, String groupName) {
        dataSource.setPoolBeanBindingPath(String.join(Constants.DOT, DynamicSourceProperties.PREFIX,
            Constants.DATA_SOURCE_MAP, groupName, Constants.MULTI_POOL_PROPERTY_APPEND));
    }

    /**
     * 组中master的绑定路径
     *
     * @param master 数据源组
     * @param groupName 组名
     */
    private void setMasterBindPath(DataSourceProperty master, String groupName) {
        Optional.ofNullable(master).ifPresent(item -> {
            item.setPoolBeanBindingPath(String.join(Constants.DOT, DynamicSourceProperties.PREFIX,
                Constants.DATA_SOURCE_MAP, groupName, Constants.DB_MASTER, Constants.MULTI_POOL_PROPERTY_APPEND));

        });
    }

    /**
     * 组中slave绑定路径
     *
     * @param slave 从
     * @param groupName 组名
     */
    private void setSlaveBindPath(List<DataSourceProperty> slave, String groupName) {
        if (CollectionUtils.isEmpty(slave)) {
            return;
        }
        for (int index = 0; index < slave.size(); index++) {
            slave.get(index)
                .setPoolBeanBindingPath(
                    String.join(Constants.DOT, DynamicSourceProperties.PREFIX, Constants.DATA_SOURCE_MAP, groupName,
                        Constants.DB_SLAVE, String.valueOf(index), Constants.MULTI_POOL_PROPERTY_APPEND));
        }
    }
}
